package cn.edu.swu.miniwebsvr.core;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class HttpParser {

    public static Parameter parse(InputStream inputStream) throws IOException {
        Parameter parameter = new Parameter();

        // TODO: [222024321072010/黄天灿]
        // 1. 读取并解析 HTTP 请求行 (e.g., GET /path?param=value HTTP/1.1)
        //    - 设置 parameter.setMethod()
        //    - 设置 parameter.setUrl()，并解析出 URL 参数 (e.g., ?param=value)，存入 parameter.urlParams
        BufferedReader reader = new BufferedReader(
        new InputStreamReader(inputStream, StandardCharsets.UTF_8));
        try {
            String requestLine = reader.readLine();
            if (requestLine == null || requestLine.isEmpty()) {
                throw new IOException("empty request");
            }
            String[] parts = requestLine.split(" ");
            if (parts.length != 3) {
                throw new IOException("bad request line");
            }
            parameter.setMethod(parts[0]);
            String fullUrl = parts[1];
            parameter.setUrl(fullUrl);

            int q = fullUrl.indexOf('?');
            if (q != -1) {
                parameter.setUrlParams(parseQueryString(fullUrl.substring(q + 1)));
                parameter.setUrl(fullUrl.substring(0, q));   // 去掉查询串的干净路径
            }
        // 2. 循环读取并解析所有 HTTP 请求头 (e.g., Host: localhost:8080)
        //    - 存入 parameter.headers
            while ( (requestLine = reader.readLine()) != null){
                if (requestLine.isEmpty()) {
                    break;
                }
                int colon = requestLine.indexOf(':');
                if (colon == -1) {
                    throw new IOException("Bad header: " + requestLine);
                }
                String name = requestLine.substring(0, colon).trim();
                String value = requestLine.substring(colon + 1).trim();
                parameter.getHeaders().put(name, value);
            }
        // 3. 根据请求方法 (Method) 和请求头 (Content-Length, Content-Type) 判断并读取请求体
        //    - 适用于 POST 请求，解析请求体中的参数，存入 parameter.bodyParams
            String method = parameter.getMethod();
            if ("POST".equalsIgnoreCase(parameter.getMethod())) {
                String contentType = parameter.getHeaders().get("content-type");
                if (contentType != null && contentType.contains("application/x-www-form-urlencoded")) {

                    /* 3.1 读取 body 文本 */
                    String body = readBody(reader, parameter.getHeaders());
                    /* 3.2 解析 key=value&key=value */
                    parameter.setBodyParams(parseQueryString(body));
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return parameter;
    }

    // TODO: [222024321072010/黄天灿] 可以添加辅助方法来简化字符串解析和 URL 解码
    private static String readBody(BufferedReader reader, Map<String, String> headers) throws IOException {
        /* 1. 优先 Content-Length */
        String cl = headers.get("content-length");
        if (cl != null) {
            int len = Integer.parseInt(cl.trim());
            char[] buf = new char[len];
            reader.read(buf, 0, len);
            return new String(buf);
        }

        /* 2. chunked */
        if ("chunked".equalsIgnoreCase(headers.get("transfer-encoding"))) {
            return readChunked(reader);
        }

        /* 3. 都没有，认为无 body */
        return "";
    }
    private static String readChunked(BufferedReader reader) throws IOException {
        StringBuilder sb = new StringBuilder();
        while (true) {
            String chunkSizeLine = reader.readLine();
            if (chunkSizeLine == null) break;
            int chunkSize = Integer.parseInt(chunkSizeLine.trim(), 16); // 16 进制长度
            if (chunkSize == 0) {
                reader.readLine(); // 最后空行
                break;
            }
            char[] buf = new char[chunkSize];
            reader.read(buf, 0, chunkSize);
            sb.append(buf);
            reader.readLine(); // 每个 chunk 后的 CRLF
        }
        return sb.toString();
    }
    private static Map<String, String> parseQueryString(String raw) {
        Map<String, String> map = new HashMap<>();
        if (raw == null || raw.isEmpty()) return map;

        // 去掉路径部分，只保留 ? 后面
        int q = raw.indexOf('?');
        if (q != -1) raw = raw.substring(q + 1);

        String[] pairs = raw.split("&");
        for (String pair : pairs) {
            String[] kv = pair.split("=", 2);
            String key = urlDecode(kv[0]);
            String val = kv.length > 1 ? urlDecode(kv[1]) : "";
            map.put(key, val);
        }
        return map;
    }
    private static String urlDecode(String s) {
        try {
            return URLDecoder.decode(s, StandardCharsets.UTF_8);
        } catch (Exception e) {
            return s;
        }
    }

}